package com.netintech.core.aspectj;

import com.netintech.common.exception.ExtalInterfaceException;
import com.netintech.common.utils.CollectionUtils;
import com.netintech.common.utils.SignUtil;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.servlet.HandlerMapping;

import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * 签名切面类
 * @author y
 */
@Aspect
@Component
public class SignAspect {

    /**时间戳参数名*/
    private static final String TIMESTAMP = "timestamp";

    /**时间戳间隔1分钟*/
    private static final Integer TIME_INTERVAL = 60000;

    /**
     * 处理完请求后执行
     *
     */
    @Before(value = "@annotation(com.netintech.core.aspectj.lang.annotation.Sign)")
    public void doBefore() throws Throwable {
        checkSign();
    }

    private void checkSign() throws Exception {
        HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
        String oldSign = request.getHeader("X-SIGN");
        if (StringUtils.isBlank(oldSign)) {
            throw new ExtalInterfaceException("Header中无[X-SIGN]签名信息");
        }
        //获取body（对应@RequestBody）
        String body = null;
        if (null!=request && null!=request.getInputStream()) {
            body = IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8);
        }

        //获取parameters（对应@RequestParam）
        Map<String, String[]> params = null;
        if (CollectionUtils.isNotEmpty(request.getParameterMap())) {
            params = request.getParameterMap();
            if (params.containsKey(TIMESTAMP)) {
                String timestamp = params.get(TIMESTAMP)[0];
                //验证时间戳
                Long timestampL = new Long(timestamp);
                Long nowTimeStamp = System.currentTimeMillis();
                if (Math.abs(timestampL - nowTimeStamp) > TIME_INTERVAL) {
                    throw new ExtalInterfaceException("时间戳超过5分钟， 请求过期");
                }
            }
        }else{
            throw new ExtalInterfaceException("QueryString无时间戳【timestamp】信息");
        }

        //获取path variable（对应@PathVariable）
        String[] paths = null;
        ServletWebRequest webRequest = new ServletWebRequest(request, null);
        Map<String, String> uriTemplateVars = (Map<String, String>) webRequest.getAttribute(
                HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
        if (!CollectionUtils.isEmpty(uriTemplateVars)) {
            paths = uriTemplateVars.values().toArray(new String[]{});
        }
        try {
            String newSign = SignUtil.sign(body, params, paths);
            if (!newSign.equals(oldSign)) {
                throw new ExtalInterfaceException("签名不一致");
            }
        } catch (Exception e) {
            throw new ExtalInterfaceException("校验签名出错", e);
        }
    }
}
